package top.haijunit.mark.common.core.config;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import top.haijunit.mark.common.core.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import top.haijunit.mark.common.core.utils.ErrorUtil;

import javax.servlet.http.HttpServletRequest;
import java.nio.file.AccessDeniedException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author 百旺张
 * @Date 2021/11/10
 * @description
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /** 不支持的请求类型 */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public Result<String> handleException(HttpRequestMethodNotSupportedException e) {
        log.error(ErrorUtil.errorInfoToString(e));
        return Result.failed("不支持' " + e.getMethod() + "'请求");
    }

    /** 拦截JSON参数校验 */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result<List<JSONObject>> argumentsHandler(MethodArgumentNotValidException e) {
        log.error(ErrorUtil.errorInfoToString(e));
        List<JSONObject> list = e.getBindingResult().getFieldErrors().stream().map(fieldError -> {
            JSONObject json = JSONUtil.createObj();
            json.set("field", fieldError.getField());
            json.set("messages", fieldError.getDefaultMessage());
            return json;
        }).collect(Collectors.toList());
        return Result.failed(list, "参数格式错误");
    }

    @ExceptionHandler(value = AccessDeniedException.class)
    public Result<Object> accessDeniedHandler(Exception e) {
        log.error(ErrorUtil.errorInfoToString(e));
        return Result.failed(e.getMessage());
    }

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(BindException.class)
    public Result<String> bindExceptionHandler(BindException exception) {
        return Result.failed(exception.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining()));
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<String> exceptionHandler(HttpServletRequest req, Exception e) {
        log.error(ErrorUtil.errorInfoToString(e));
        return Result.failed(req.getRequestURI(), e.getMessage());
    }

    @ExceptionHandler(value = ArithmeticException.class)
    public Result<String> arithmeticExceptionHandler(HttpServletRequest req, Exception e) {
        log.error(ErrorUtil.errorInfoToString(e));
        return Result.failed(req.getRequestURI(), e.getMessage());
    }
}
